﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.DirectX; //for Vector3
using Microsoft.DirectX.Direct3D;

namespace DirectX_CS
{
	public interface IManagedModelTransformable : IModelTransformable
	{
		void UpdateTransform();
	}
	public interface IModelTransformable : IRecreatable
	{
		TransformMatrix ModelView { get; set; }
	}
	public class TransformMatrix
	{
		bool needsRecreate = true;
		[PGBrowsable]
		public bool NeedsRecreate
		{
			get { return needsRecreate; }
		}

		public TransformMatrix Clone()
		{
			return (TransformMatrix)this.MemberwiseClone();
		}

		public TransformMatrix()
		{
			modelMatrix = Matrix.Identity;
			position = new Vector3(0, 0, 0);
			//needsRecreate = true;//already set
		}
		[PGBrowsable]
		public Vector3 Position
		{
			get { return position; }
			set { 
				if (position != value)
				{
					position = value;
					needsRecreate = true;
				}
			}
		}
		private bool useRotation = true;
		[PGBrowsable]
		public bool UseRotation
		{
			get { return useRotation; }
			set {
				if (useRotation != value)
				{
					needsRecreate = true;
					useRotation = value;
				}
			}
		}
		protected float scaleX = 1, scaleY = 1, scaleZ = 1;
		[PGBrowsable]
		public float ScaleZ
		{
			get { return scaleZ; }
			set
			{
				if (scaleZ != value)
				{
					scaleZ = value;
					needsRecreate = true;
				}
			}
		}
		[PGBrowsable]
		public float ScaleY
		{
			get { return scaleY; }
			set { 
				if (scaleY != value)
				{
					scaleY = value;
					needsRecreate = true;
				}
			}
		}
		[PGBrowsable]
		public float ScaleX
		{
			get { return scaleX; }
			set {
				if (scaleX != value)
				{
					scaleX = value;
					needsRecreate = true;
				}
			
			}
		}
		[PGBrowsable]
		public Vector3 Scale
		{
			get { return new Vector3(scaleX, scaleY, scaleZ); }
			set
			{
				if (Scale != value)
				{
					scaleX = value.X;
					scaleY = value.Y;
					scaleZ = value.Z;
					needsRecreate = true;
				}
			}
		}

		protected bool useScaling = true;
		[PGBrowsable]
		public bool UseScaling
		{
			get { return useScaling; }
			set { 
				if (useScaling != value)
				{
					if (Scale == new Vector3(1, 1, 1))
					{
						needsRecreate = true;
					}
					useScaling = value;
				}
			}
		}
		public Matrix RecreateMatrix()
		{
			if (needsRecreate)
			{
				Matrix scaling = Matrix.Scaling(scaleX, scaleY, scaleZ);

				if (useScaling)
					modelMatrix = scaling;
				else
					modelMatrix = Matrix.Identity;

				Matrix translation = Matrix.Translation(position);

				if (useRotation)
				{
					Matrix rotation = Matrix.RotationYawPitchRoll(yaw, pitch, roll) *
						Matrix.RotationX(rotationX) *
						Matrix.RotationY(rotationY) *
						Matrix.RotationZ(rotationZ) *
						Matrix.RotationAxis(axisOfRotation, rotationAxisAngle);
					modelMatrix = modelMatrix * rotation * translation;

				}
				else
					modelMatrix = modelMatrix * translation;

				//now finally set this property so recreation does not constantly have to be done for each frame for instance
				needsRecreate = false;
			}
			//careful here if a property does not properly set needsREcreaate then it will not create as needed.
			//so be careful to set the needsRecreate property when other properties change.
			return modelMatrix;
		}

		protected Matrix modelMatrix;
		protected Vector3 position;
		[PGBrowsable]
		public float X
		{
			get { return position.X; }
			set {
				if (position.X != value)
				{
					needsRecreate = true;
					position.X = value; 
				}
			}
		}

		[PGBrowsable]
		public float Y
		{
			get { return position.Y;}
			set
			{

				if (position.Y != value)
				{
					needsRecreate = true;
					position.Y = value;
				}
			}
		}
		[PGBrowsable]
		public float Z
		{
			get { return position.Z; }
			set
			{
				if (position.Z != value)
				{
					needsRecreate = true;
					position.Z = value;
				}
			}
		}
		private float yaw = 0;
		[PGBrowsable]
		public float Yaw
		{
			get { return yaw; }
			set 
			{ 
				if (yaw != value)
				{
					yaw = value;
					needsRecreate = true;
				}
			}
		}
		private float pitch = 0;
		[PGBrowsable]
		public float Pitch
		{
			get { return pitch; }
			set
			{
				if (pitch != value)
				{
					needsRecreate = true;
					pitch = value;
				}
			}
		}
		private float roll = 0;
		[PGBrowsable]
		public float Roll
		{
			get { return roll; }
			set {
				if (roll != value)
				{
					roll = value;
					needsRecreate = true;
				}
			}
		}

		private float rotationX = 0;
		[PGBrowsable]
		public float RotationX
		{
			get { return rotationX; }
			set
			{
				if (rotationX != value)
				{
					needsRecreate = true;
					rotationX = value;
				}
			}
		}
		private float rotationY = 0;
		[PGBrowsable]
		public float RotationY
		{
			get { return rotationY; }
			set 
			{
				if (rotationY != value)
				{
					rotationY = value;
					needsRecreate = true;
				}
			}
		}
		private float rotationZ = 0;
		[PGBrowsable]
		public float RotationZ
		{
			get { return rotationZ; }
			set
			{
				if (rotationZ != value)
				{
					rotationZ = value;
					needsRecreate = true;
				}
			}
		}
		private Vector3 axisOfRotation = new Vector3(1, 0, 0);
		[PGBrowsable]
		public Vector3 AxisOfRotation
		{
			get { return axisOfRotation; }
			set {
				if (axisOfRotation != value)
				{
					axisOfRotation = value;
					needsRecreate = true;
				}
			}
		}
		private float rotationAxisAngle = 0;
		[PGBrowsable]
		public float RotationAxisAngle
		{
			get { return rotationAxisAngle; }
			set {
				if (rotationAxisAngle != value)
				{
					rotationAxisAngle = value;
					needsRecreate = true;
				}
			}
		}

 	}
}
